/**
 * 
 */
package thread;

/**
 * @author Michael
 * http://www.ibm.com/developerworks/java/library/j-dcl/index.html
 * 
 * It is NOT guarantee to work properly in any JVM implementation
 * Check that the variable is initialized (without obtaining the lock). 
 * If it is initialized, return it immediately.
 * Obtain the lock.
 * Double-check whether the variable has already been initialized: if another thread acquired the lock first, it may have already done the initialization. If so, return the initialized variable.
 * Otherwise, initialize and return the variable.
 */
public class DoubleCheckedLockedSingleton {

	public static class DoubleCheckedLocked {
		private static DoubleCheckedLocked instance;

		public DoubleCheckedLocked getInstance() {
			if (instance == null) {
				synchronized (this) {
					if (instance == null)
						instance = new DoubleCheckedLocked();
				}
			}
			return instance;
		}
	}
	
	// Synchronized singleton
	public static class SynchronizedSingleton {
		private static SynchronizedSingleton instance = null;

		private SynchronizedSingleton() { ; }
		
		public static synchronized SynchronizedSingleton getInstance() {
			if (instance == null) {
				instance = new SynchronizedSingleton();
			}
			return instance;
		}
	}
	
	// Eager singleton
	public static class EagerSingleton {
		private static EagerSingleton instance = new EagerSingleton();

		private EagerSingleton() { ; }
		
		public static EagerSingleton getInstance() {
			return instance;
		}
	}
	
	/**
	 * 
	 */
	public DoubleCheckedLockedSingleton() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}

}
